package com.evan.framework.core.base;

import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * @Description: 所有result的基类
 * @Author liudeguang
 */
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class BaseResult<T> {
    /**
     * 返回码
     */
    private String code;

    /**
     * 返回信息
     */
    private String message;

    /**
     * 返回数据
     */
    private T data;

    public BaseResult() {
    }

    public BaseResult(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public BaseResult(String code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public void setCode(String code) {
        if (code != null) {
            this.code = code;
        }
    }

    @JsonIgnore
    @JSONField(serialize = false)
    public boolean isSuccess() {
        return StringUtils.equals(BaseEnum.SUCCESS.getCode(), code);
    }

    public static BaseResult defaultResult(AbstractResponse response) {
        BaseResult httpResponse = new BaseResult();
        httpResponse.setCode(response.getCode());
        httpResponse.setMessage(response.getMessage());
        return httpResponse;
    }

    public static <M> BaseResult<M> defaultResult(AbstractResponse response, M result) {
        BaseResult<M> httpResponse = new BaseResult<>();
        httpResponse.setCode(response.getCode());
        httpResponse.setMessage(response.getMessage());
        httpResponse.setData(result);
        return httpResponse;
    }

    public static <M> BaseResult<M> defaultResult(AbstractResponse response, Supplier<M> supplier) {
        BaseResult<M> httpResponse = new BaseResult();
        httpResponse.setCode(response.getCode());
        httpResponse.setMessage(response.getMessage());
        httpResponse.setData(supplier.get());
        return httpResponse;
    }

    public static <M> BaseResult pageResult(AbstractPagedResponse<M> response) {
        BaseResult httpResponse = new BaseResult();
        httpResponse.setCode(response.getCode());
        httpResponse.setMessage(response.getMessage());
        if (response.isSuccess()) {
            PageResult pageResult = new PageResult();
            pageResult.setList(response.getDatas());
            pageResult.setTotal(response.getTotal());
            httpResponse.setData(pageResult);
        }
        return httpResponse;
    }

    public static <M> BaseResult pageResult(AbstractPagedResponse<M> response, Function<List, List> function) {
        BaseResult httpResponse = new BaseResult();
        httpResponse.setCode(response.getCode());
        httpResponse.setMessage(response.getMessage());
        if (response.isSuccess()) {
            PageResult pageResult = new PageResult();
            pageResult.setList((List) function.apply(response.getDatas()));
            pageResult.setTotal(response.getTotal());
            httpResponse.setData(pageResult);
        }
        return httpResponse;
    }

    public static <M> BaseResult defaultSuccess() {
        BaseResult resp = new BaseResult();
        resp.setCode(BaseEnum.SUCCESS.getCode());
        resp.setMessage(BaseEnum.SUCCESS.getDesc());
        return resp;
    }

    public static <M> BaseResult defaultSuccess(M data) {
        BaseResult<M> resp = new BaseResult<>();
        resp.setData(data);
        resp.setCode(BaseEnum.SUCCESS.getCode());
        resp.setMessage(BaseEnum.SUCCESS.getDesc());
        return resp;
    }


    public static BaseResult pageSuccess(List<?> data, Integer total) {
        BaseResult resp = new BaseResult();
        PageResult pageResult = new PageResult();
        pageResult.setList(data);
        pageResult.setTotal(total);
        resp.setData(pageResult);
        resp.setCode(BaseEnum.SUCCESS.getCode());
        resp.setMessage(BaseEnum.SUCCESS.getDesc());
        return resp;
    }

    @Data
    public final static class PageResult<M> {

        private Integer total;

        private List<M> list;
    }

    public static BaseResult fail(String code, String message) {
        BaseResult resp = new BaseResult();
        resp.setCode(code);
        resp.setMessage(message);
        return resp;
    }

    public static BaseResult defaultFail(String code) {
        BaseResult resp = new BaseResult();
        resp.setCode(code);
        resp.setMessage(BaseEnum.FAIL.getDesc());
        return resp;
    }
}
